/* 
*  Copyright (C) 2009-2010 WCG Project
*
*  This program is free software; you can redistribute it and/or modify it
*  under the terms of the GNU General Public License as published by the
*  Free Software Foundation; either version 2 of the License, or (at
*  your option) any later version.
*
*  This program is distributed in the hope that it will be useful, but
*  WITHOUT ANY WARRANTY; without even the implied warranty of
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
*  General Public License for more details.
*
*  You should have received a copy of the GNU General Public License
*  along with this program; if not, write to the Free Software Foundation,
*  Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*  In addition, as a special exception, the author gives permission to
*  link the code of this program with the Half-Life Game Engine ("HL
*  Engine") and Modified Game Libraries ("MODs") developed by Valve,
*  L.L.C ("Valve"). You must obey the GNU General Public License in all
*  respects for all of the code used other than the HL Engine and MODs
*  from Valve. If you modify this file, you may extend this exception
*  to your version of the file, but you are not obligated to do so. If
*  you do not wish to do so, delete this exception statement from your
*  version.
*/



//-----------------------------------------
// Register_Events()
//
//-----------------------------------------
public Register_Events()
{
	register_logevent( "OnPlayerAction", 		3, "1=triggered" )
	register_logevent( "OnStartRound",			2, "1=Round_Start" )
	register_logevent( "OnEndRound", 			2, "1=Round_End" )
	register_logevent( "OnTeamJoin",			3, "1=joined team")

	register_event( "CurWeapon",	"OnCurWeapon",			"be", "1=1" )
	register_event( "HideWeapon",	"OnCurWeapon",			"b" )
	register_event( "TextMsg",		"OnGameRestart",		"a", "2&#Game_will_restart_in" )
	register_event( "HLTV",			"OnNewRound",			"a", "1=0", "2=0" )
	register_event( "SendAudio",	"OnTerroristWin",		"a", "2=%!MRAD_terwin" )
	register_event( "SendAudio",	"OnCTWin", 				"a", "2=%!MRAD_ctwin" )
	register_event( "ArmorType",	"OnArmorType",			"be" )
	register_event( "Battery",		"OnBattery",			"be" )
	register_event( "WeapPickup",	"OnWeapPickup",			"b" )
	register_event( "StatusValue",	"OnShowStatus",			"be", "1=2", "2!0" )
	register_event( "StatusValue",	"OnHideStatus",			"be", "1=1", "2=0" )
	register_event( "SetFOV",		"OnZoom",				"be" )
	register_event( "BarTime",		"OnBombPlanting",		"be", "1=3" )
	register_event( "BarTime",		"OnBombStopPlanting",	"b", "1=0" )
	register_event( "ScreenFade", 	"OnFlashed", 			"be", "4=255", "5=255", "6=255", "7>199" ) 
	register_event( "35",			"OnWeaponAnim",			"b" )

	register_event( "TextMsg",		"OnTeamJoin",			"a", "1=1", "2=#Game_join_terrorist", "2=#Game_join_ct" )
	register_event( "TeamInfo",		"OnSpecJoin",			"a", "1>0", "2=SPECTATOR")

	if ( GameInfo[GI_Mod] == GAME_CZERO )
		register_event("TextMsg",	"OnGameRestart",		"a", "2&#Game_Commencing")
	else
		register_event("TextMsg",	"OnGameRestart",		"a", "2&#Game_C") // Counter-Strike


	// Call Round Start
	set_task(1.0, "OnNewRound")
}


//-------------------------------------------
// OnTeamJoin
//
//-------------------------------------------
public OnTeamJoin()
{
	WCG_SortTeams()
}


//-------------------------------------------
// OnSpecJoin
//
//-------------------------------------------
public OnSpecJoin()
{
	WCG_SortTeams()
}



//-------------------------------------------
// OnPlayerAction
//
// Called on certain player events
//-------------------------------------------
public OnPlayerAction()
{
	static sArg[64], sAction[64], sName[64]
	new iUserId, id

	read_logargv( 0,sArg,64 )
	read_logargv( 2,sAction,64 )
	parse_loguser( sArg,sName,64,iUserId )
	id = find_player( "k", iUserId )

	if( !is_user_alive(id) || GameInfo[GI_EndRound] )
		return PLUGIN_CONTINUE


	// Spawned with the bomb 
	if(equal(sAction,"Spawned_With_The_Bomb"))
	{
		PlayerInfo[id][PI_PlayerRole] = PLR_BOMB_CARRIER
		new iBonusXP = XP_Give( id, SPAWN_BOMB )

		if ( iBonusXP != 0 )
			client_print( id, print_chat, "%s You have been awarded %d XP for spawning with the bomb", g_MODclient, iBonusXP )
	}

	// Dropped bomb 
	else if (equal(sAction,"Dropped_The_Bomb"))
	{
		PlayerInfo[id][PI_PlayerRole] = 0
		new iBonusXP = XP_Give( id, -1 * BOMB_PICKUP )

		if ( iBonusXP != 0 )
			client_print( id, print_chat, "%s You have lost %d XP for dropping the bomb", g_MODclient, -1 * iBonusXP )
	}

	// Picked up bomb 
	else if (equal(sAction,"Got_The_Bomb"))
	{ 
		PlayerInfo[id][PI_PlayerRole] = PLR_BOMB_CARRIER
		new iBonusXP = XP_Give( id, BOMB_PICKUP )

		if ( iBonusXP != 0 )
			client_print( id, print_chat, "%s You have been awarded %d XP for picking up the bomb", g_MODclient, iBonusXP )
	}

	// Hostage touched 
	else if (equal(sAction,"Touched_A_Hostage"))
	{
		PlayerInfo[id][PI_PlayerRole] = PLR_HOSTAGE_RESCUER
		new iBonusXP = XP_Give( id, TOUCH_HOSTAGE )

		if ( iBonusXP != 0 )
			client_print( id, print_chat, "%s You have been awarded %d XP for starting to rescue a hostage", g_MODclient, iBonusXP )
	}

	// Hostage rescued 
	else if (equal(sAction,"Rescued_A_Hostage"))
	{
		new iBonusXP = XP_Give( id, RESCUE_HOSTAGE )

		if ( iBonusXP != 0 )
			client_print( id, print_chat, "%s You have been awarded %d XP for rescuing a hostage", g_MODclient, iBonusXP )
	}

	// Hostage killed 
	else if (equal(sAction,"Killed_A_Hostage"))
	{
		new iBonusXP = XP_Give( id, -1 * KILL_HOSTAGE )

		if ( iBonusXP != 0 )
			client_print( id, print_chat, "%s You have lost %d XP for killing a hostage", g_MODclient, -1 * iBonusXP )
	}

	// VIP spawn 
	else if (equal(sAction,"Became_VIP"))
	{ 
		PlayerInfo[id][PI_PlayerRole] = PLR_VIP
		new iBonusXP = XP_Give( id, SPAWN_VIP )

		if ( iBonusXP != 0 )
			client_print( id, print_chat, "%s You have gained %d XP for spawning as the VIP", g_MODclient, iBonusXP )
	}

	// VIP escaped 
	else if (equal(sAction,"Escaped_As_VIP"))
	{
		new iBonusXP = XP_Give( id, ESCAPE_VIP )

		if ( iBonusXP != 0 )
			client_print( id, print_chat, "%s You have gained %d XP for escaping as the VIP", g_MODclient, iBonusXP )
	}

	return PLUGIN_CONTINUE
}



//-------------------------------------------
// OnFreezeTimeComplete
//
// Called when freezetime is over
//-------------------------------------------
public OnStartRound()
{
	GameInfo[GI_FreezeTime] = false
	
	// Loop through all players
	for( new id = 1 ; id <= GameInfo[GI_MaxPlayers] ; id++ )
	{
		if( !is_user_connected(id) || !IsOnTeam(id) )
			continue
		
		// Show them their race/xp/item bar
		WC3_ShowBar( id )

		// Award speed bonuses (if any)
		set_task( 0.1, "PLAYER_UpdateSpeed", TASK_DELAYEDFUNCTION + id )
	}
	return PLUGIN_CONTINUE
}



//-------------------------------------------
// OnEndRound
//
// Called when round is over
//-------------------------------------------
public OnEndRound()
{
	static Float:lastendtime
	if( get_gametime() - lastendtime < 0.5 )	// Prevent this from getting called twice when restarting (bugfix)
		return PLUGIN_CONTINUE

	lastendtime = get_gametime()

	GameInfo[GI_EndRound] = true

	return PLUGIN_CONTINUE
}


//-------------------------------------------
// OnCurWeapon
//
//-------------------------------------------
public OnCurWeapon( id )
{
	static iLastCurWeapon[33]

	if( !is_user_alive(id) )
		return PLUGIN_CONTINUE

	new bIsActive	= read_data(1)
	new iCurWeapon	= read_data(2)
	new iAmmo		= read_data(3)

	PlayerInfo[id][PI_CurrentWeapon] = iCurWeapon

	// Then a weapon strip was triggered - we don't want to save now do we?
	if ( !iCurWeapon && !bIsActive && !iAmmo )
		return PLUGIN_CONTINUE

	// Save the user's weapons
	SHARED_SaveWeapons( id )

	if( PlayerInfo[id][PI_Stealthed] || PlayerInfo[id][PI_IsPolymorphed] )
	{
		engclient_cmd( id, "weapon_knife" )
		iLastCurWeapon[id] = CSW_KNIFE
		PLAYER_UpdateSpeed( id )
		return PLUGIN_CONTINUE
	}

	// We only need to run these functions if the user's weapon has changed since our last function call!
	else if( iLastCurWeapon[id] != iCurWeapon )
		PLAYER_UpdateSpeed( id )

	iLastCurWeapon[id] = iCurWeapon
	
	return PLUGIN_CONTINUE
}



//-------------------------------------------
// OnGameRestart
//
//-------------------------------------------
public OnGameRestart()
{
	// Save all XP on game restart - do not do this threaded or it might take 300 years
	DB_SaveAll( false )

	GameInfo[GI_GameRestarting] = true
	
	return PLUGIN_CONTINUE
}



//-------------------------------------------
// OnNewRound
//
// Function is called ONCE at the start of a new round BEFORE user's spawn
//-------------------------------------------
public OnNewRound()
{
	// Hack solution until the real cause of the "bomb explodes after round"-bug
	new bomb
	if((bomb = fm_find_ent_by_model(-1, "grenade", "models/w_c4.mdl")))
	{
		if( pev_valid(bomb) )
			fm_remove_entity(bomb) // remove the planted bomb
	}


	remove_task( TASK_DELAYED_DAMAGE )
	remove_task( TASK_EFFECT )

	GameInfo[GI_BombPlanted] = false

	// User's have not spawned yet, so lets do some pre-spawn things
	for( new id = 1; id <= GameInfo[GI_MaxPlayers] ; id++ )
	{
		if( is_user_connected(id) )
			WC3_NewRound( id )
	}
	
	// Reset which spawn points are reserved....
	_SHARED_SpawnReset()

	// If someone restarted the game, then lets reset war3
	if( GameInfo[GI_GameRestarting] )
		WC3_ResetGame()
	
	// We need to determine when the buytime is up
	if( get_pcvar_num( CVAR_buy_time ) )
	{
		// Remove our buytime task if it exists (from a previous round)
		remove_task( TASK_BUYTIME )

		GameInfo[GI_BuyTime] = true

		set_task( get_cvar_float("mp_buytime") * 60.0, "_CS_BuyTimeOver", TASK_BUYTIME )
	}

	GameInfo[GI_FreezeTime] = true
	GameInfo[GI_EndRound] = false

	// Schedule the fortitude buff
	set_task( 1.5, "_PRIEST_BuffFortitude", TASK_EFFECT )

	// Schedule the blessing of kings buff
	set_task( 2.5, "_PALADIN_BuffBoK", TASK_EFFECT )

	return PLUGIN_CONTINUE
}



//-------------------------------------------
// OnTerroristWin
//
//-------------------------------------------
public OnTerroristWin()
{
	XP_WinRound( TEAM_T )

	set_task( 0.0, "_EndRound", TASK_DELAYEDFUNCTION )
	return PLUGIN_CONTINUE
}



//-------------------------------------------
// OnCTWin
//
//-------------------------------------------
public OnCTWin()
{
	XP_WinRound( TEAM_CT )

	set_task( 0.0, "_EndRound", TASK_DELAYEDFUNCTION )
	return PLUGIN_CONTINUE
}



//-------------------------------------------
// _EndRound
//
// Task called next gameloop update after OnEndRound
//-------------------------------------------
public _EndRound()
{
	XP_RoundEnd()

	// Save XP at the end of the round?
	if( get_pcvar_num( CVAR_save_end_round ) )
		DB_SaveAll( true )			// Threaded saves on end round!
}




//-------------------------------------------
// OnArmorType
//
//-------------------------------------------
public OnArmorType(id)
{
	// Save user's armor
	PlayerInfo[id][PI_ArmorOnDeath] = cs_get_user_armor( id, PlayerInfo[id][PI_ArmorType] )
	return PLUGIN_CONTINUE
}



//-------------------------------------------
// OnBattery
//
// Function called when a user's armor changes
//-------------------------------------------
public OnBattery( id )
{	
	if( !bIgnoreArmorSet[id] )
	{
		// Store the previous value (we do this b/c the Battery event is triggered (and set to 0) before weapon reincarnation)
		PlayerInfo[id][PI_LastArmor] 	= PlayerInfo[id][PI_ArmorOnDeath]
		PlayerInfo[id][PI_ArmorOnDeath]	= read_data( 1 )
	}
	return PLUGIN_CONTINUE
}



//-------------------------------------------
// OnWeapPickup
//
//-------------------------------------------
public OnWeapPickup( id )
{ 
	SHARED_SaveWeapons( id )
	return PLUGIN_CONTINUE
}



//-------------------------------------------
// OnShowStatus
//
// Event triggered when you look at another player
//-------------------------------------------
public OnShowStatus( id )
{
	if( !is_user_alive(id) )
		return PLUGIN_CONTINUE

	WCG_UpdateStatusBar( id )

	new iTarget = read_data( 2 )
	new iTargetTeam = PlayerInfo[iTarget][PI_TeamID]
	new iViewerTeam = PlayerInfo[id][PI_TeamID]

	// Show player information on screen?
	if( !GameInfo[GI_FreezeTime] && get_pcvar_num( CVAR_show_player ) )
	{
		new iRed = 0, iBlue = 0, bool:bShowAsTeammate = false;

		if( PlayerInfo[iTarget][PI_Stealthed] > 0 )
		{
			PlayerInfo[id][PI_StatusText] = 0
			return PLUGIN_CONTINUE
		}


//		new szTargetName[32];
//		get_user_name( iTarget, szTargetName, 31 )
		
		// The target looks like the enemy o.O
		if ( PlayerInfo[iTarget][PI_SkinSwitched] )
		{
			// Then the viewer should see the user's true color!
			if( ITEM_Has( id, ITEM_PROTECTANT ) > ITEM_NONE )
			{
				iRed = ( iTargetTeam == TEAM_T ) ? 255 : 0
				iBlue = ( iTargetTeam == TEAM_CT ) ? 255 : 0
			}

			// Lets "camouflage" them
			else
			{
				iRed = ( iTargetTeam == TEAM_T ) ? 255 : 0
				iBlue = ( iTargetTeam == TEAM_CT ) ? 255 : 0

				bShowAsTeammate = true
			}
		}
		
		// Lets just set the correct colors
		else
		{
			iRed = ( iTargetTeam == TEAM_T ) ? 255 : 0
			iBlue = ( iTargetTeam == TEAM_CT ) ? 255 : 0
		}

		// Set up the hud message
		set_hudmessage( iRed, 30, iBlue, _, 0.55, 0, 0.0, 200.0, 0.1, 0.0, HUD_SHOWSTATUS )

		PlayerInfo[id][PI_StatusTextColor] = COLOR_RGB( iRed, 0, iBlue )

		// Teammate or should look like teammate
		if( iViewerTeam == iTargetTeam || bShowAsTeammate )
			formatex( PlayerInfo[id][PI_StatusText], 31, "%s -- %d HP / %d AP", PlayerInfo[iTarget][PI_PlayerName], get_user_health( iTarget ), get_user_armor( iTarget ) )
		else
			formatex( PlayerInfo[id][PI_StatusText], 31, "%s", PlayerInfo[iTarget][PI_PlayerName] )		// Enemy

		ShowSyncHudMsg( id, g_HUDSync_StatusText, PlayerInfo[id][PI_StatusText] )
	}
	return PLUGIN_CONTINUE
}



//-------------------------------------------
// OnHideStatus
//
// This is called when the user is no longer viewing the player
//-------------------------------------------
public OnHideStatus( id )
{
	if( get_pcvar_num( CVAR_show_player ) && !GameInfo[GI_FreezeTime] )
	{
		static iRed, iBlue

		if( PlayerInfo[id][PI_StatusText] == 0 )
			return PLUGIN_CONTINUE

		iRed	= COLOR_RED( PlayerInfo[id][PI_StatusTextColor] )
		iBlue	= COLOR_BLUE( PlayerInfo[id][PI_StatusTextColor] )

		set_hudmessage( iRed, 30, iBlue, _, 0.55, 0, 0.0, 0.5, 0.0, 0.5, HUD_SHOWSTATUS )
		ShowSyncHudMsg( id, g_HUDSync_StatusText, PlayerInfo[id][PI_StatusText] )
	}
	return PLUGIN_CONTINUE
}



//-------------------------------------------
// OnZoom
//
// From war3x
//-------------------------------------------
public OnZoom( id )
{
	if ( read_data( 1 ) < 90 )
		PlayerInfo[id][PI_IsZoomed] = true
	else
		PlayerInfo[id][PI_IsZoomed] = false

	// We will need to change the user's speed on zooming
	PLAYER_UpdateSpeed( id )
	return PLUGIN_CONTINUE
}



//-------------------------------------------
// OnBombPlanting
//
//-------------------------------------------
public OnBombPlanting( id )
{
	PlayerInfo[id][PI_IsPlantingDefusing] = true
	return PLUGIN_CONTINUE
}



//-------------------------------------------
// OnBombStopPlanting
//
//-------------------------------------------
public OnBombStopPlanting( id )
{
	PlayerInfo[id][PI_IsPlantingDefusing] = false
	return PLUGIN_CONTINUE
}



//-------------------------------------------
// OnFlashed
//
// This will "prevent" EFFECT_ScreenFade from overriding flashed players
// with new shorter fades like from vampiric embrace and such
//-------------------------------------------
public OnFlashed( id )
{
	if( !is_user_alive(id) || is_user_bot(id) )
		return PLUGIN_CONTINUE

	new alpha = read_data(7)

	if( alpha >= 200 )
	{
		new Float:duration = float(read_data(1)) / (1<<12)
		new Float:hold = float(read_data(2)) / (1<<12)
		
		PlayerInfo[id][PI_IsFlashed] = true
		
		duration *= alpha/255.0

		// Tone down duration time since the player is able to see after a little while anyway
		duration *= 0.6
		
		duration += hold

		set_task( duration, "_ResetFlashed", TASK_DELAYEDFUNCTION + id )
	}

	return PLUGIN_CONTINUE
}


//-------------------------------------------
// _ResetFlashed
//
//-------------------------------------------
public _ResetFlashed( id )
{
	id = GetTaskID( id, TASK_DELAYEDFUNCTION )

	PlayerInfo[id][PI_IsFlashed] = false
}



//-------------------------------------------
// OnWeaponAnim
//
// Weapon Animation Event
//-------------------------------------------
public OnWeaponAnim()
{
	// Because of a weird bug within the AMXX event system, we need to
	// hook this message to prevent some weird behavior when calling
	// engclient_cmd(id, "weapon_knife")
	// http://forums.alliedmods.net/showthread.php?t=85161&page=2
}
